﻿//*************************************************************************************************
// XmlTreeView.cs
// Owner: Mahipal Kante
//
// Wrapper for TreeView that bings XML to TreeView
//
// Copyright(c) Microsoft Corporation, 2010
//*************************************************************************************************
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Xml;

namespace WebTest.WebService.Plugin.ResultTab
{
    /// <summary>
    /// Wrapper for TreeView to enable XML content view
    /// </summary>
    public class XmlTreeView
    {
        private TreeView treeView;
        private XmlDocument dom;

        /// <summary>
        /// Wrapper for TreeView to enable XML content view
        /// </summary>
        /// <param name="treeView">TreeView where XML content needs to be shown</param>
        public XmlTreeView(TreeView treeView)
        {
            this.treeView = treeView;
            treeView.BeforeExpand += new TreeViewCancelEventHandler(TreeExpanded);
            treeView.AfterLabelEdit += new NodeLabelEditEventHandler(treeViewRequest_AfterLabelEdit);
        }

        /// <summary>
        /// Show XML in tree
        /// </summary>
        /// <param name="xmlString"></param>
        /// <returns></returns>
        public XmlDocument ShowXML(string xmlString)
        {
            try
            {
                // Load the XML file.
                this.dom = new XmlDocument();
                dom.LoadXml(xmlString);
                ShowXML(dom);
                return dom;
            }
            catch (Exception)
            {
                //MessageBox.Show(ex.Message, "Error");
            }
            return null;
        }

        /// <summary>
        /// Show XML in tree
        /// </summary>
        /// <param name="reader"></param>
        /// <returns></returns>
        public XmlDocument ShowXML(XmlReader reader)
        {
            try
            {
                // Load the XML file.
                this.dom = new XmlDocument();
                dom.Load(reader);
                ShowXML(dom);
                return dom;
            }
            catch (Exception)
            {
                //MessageBox.Show(ex.Message, "Error");
            }
            return null;
        }

        /// <summary>
        /// Show XML in tree
        /// </summary>
        /// <param name="dom"></param>
        public void ShowXML(XmlDocument dom)
        {
            try
            {
                this.dom = dom;
                XmlNode xNode = dom.DocumentElement;

                // Load the XML into the TreeView.
                treeView.Nodes.Clear();

                TreeNode treeNode = new TreeNode(xNode.Name);
                treeNode.Tag = xNode;
                if (xNode.HasChildNodes)
                {
                    treeNode.Nodes.Add(new TreeNode("dummy"));
                }
                else
                {
                    treeNode.Text = xNode.InnerXml.Trim();
                }

                treeView.Nodes.Add(treeNode);
                treeNode.Collapse();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Error");
            }
        }

        /// <summary>
        /// Indicates whether message has been edited since last update
        /// </summary>
        public bool MessageEdited
        {
            get;
            set;
        }

        /// <summary>
        /// replaces currently selected XML node's contents with given parameter name
        /// </summary>
        /// <param name="parameterName">name of the parameter</param>
        public void AddParameter(string parameterName)
        {
            TreeNode treeNode = this.treeView.SelectedNode;
            TreeNode parentTreeNode = treeNode.Parent;
            if (treeNode != null && parentTreeNode != null)
            {
                if (parameterName.Equals("Type Parameter"))
                {
                    if (!treeNode.IsEditing)
                    {
                        treeNode.BeginEdit();
                    }
                    return;
                }

                ParameterizeNode(treeNode, "{{" + parameterName + "}}");
            }
        }

        private void treeViewRequest_AfterLabelEdit(object sender, System.Windows.Forms.NodeLabelEditEventArgs e)
        {
            if (e.Label != null)
            {
                if (e.Label.Length > 0)
                {
                    //Stop editing without canceling the label change.
                    e.Node.EndEdit(false);
                    ParameterizeNode(e.Node, e.Label);
                }
                else
                {
                    // Cancel the label edit action, inform the user, and 
                    // place the node in edit mode again
                    e.CancelEdit = true;
                    MessageBox.Show("Invalid input.\nThe label cannot be blank",
                       "Node Label Edit");
                    e.Node.BeginEdit();
                }
            }
        }

        private void TreeExpanded(object sender, TreeViewCancelEventArgs e)
        {
            if (e.Node.Nodes.Count == 1 && e.Node.Nodes[0].Text.Equals("dummy"))
            {
                e.Node.Nodes.Clear();
                XmlNode parentNode = e.Node.Tag as XmlNode;
                XmlNodeList nodeList = parentNode.ChildNodes;
                for (int i = 0; i <= nodeList.Count - 1; i++)
                {
                    XmlNode xNode = parentNode.ChildNodes[i];
                    TreeNode treeNode = new TreeNode();
                    treeNode.Tag = xNode;
                    if (xNode.NodeType.Equals(XmlNodeType.Element))
                    {
                        treeNode.Text = xNode.Name;
                        if (xNode.HasChildNodes)
                        {
                            treeNode.Nodes.Add(new TreeNode("dummy"));
                        }
                        else
                        {
                            treeNode.Nodes.Add(new TreeNode(xNode.Value));
                        }
                    }
                    else
                    {
                        treeNode.Text = xNode.Value;
                    }

                    e.Node.Nodes.Add(treeNode);
                    treeNode.Collapse();
                }
            }
        }

        private void ParameterizeNode(TreeNode treeNode, string parameter)
        {
            TreeNode parentTreeNode = treeNode.Parent;
            XmlNode xNode = treeNode.Tag as XmlNode;
            if (xNode != null)
            {
                XmlNode parentXNode = parentTreeNode.Tag as XmlNode;
                treeNode.Text = parameter;
                if (xNode is XmlText)
                {
                    xNode.Value = parameter;
                }
                else
                {
                    XmlText textNode = dom.CreateTextNode(parameter);
                    parentXNode.ReplaceChild(textNode, xNode);
                    treeNode.Tag = textNode;
                    treeNode.Nodes.Clear();
                }
                this.MessageEdited = true;
            }
        }
    }
}
